package io.netty.nettygateway.outbound.okhttp;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.nettygateway.filter.HeaderHttpResponseFilter;
import io.netty.nettygateway.filter.HttpRequestFilter;
import io.netty.nettygateway.filter.HttpResponseFilter;
import lombok.SneakyThrows;
import okhttp3.*;

import java.io.IOException;
import java.util.concurrent.Semaphore;

import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * @author
 */
public class OkHttpOutboundHandler {
    private static final OkHttpClient okHttpClient = OkHttpClientObject.CLIENT.getClientInstance();

    private static Semaphore semaphore = new Semaphore(0);


    public static Semaphore getSemaphoreInstance(){
        return semaphore;
    }

    private String originServerUrl;

    HttpResponseFilter responseFilter = new HeaderHttpResponseFilter();


    public OkHttpOutboundHandler(String url) {
        this.originServerUrl = formatUrl(url);
    }

    private String formatUrl(String backend) {
        return backend.endsWith("/")?backend.substring(0,backend.length()-1):backend;
    }

    public void handle(final FullHttpRequest fullRequest, final ChannelHandlerContext ctx, HttpRequestFilter filter) {
        final String url = originServerUrl + fullRequest.uri();
        filter.filter(fullRequest, ctx);
        fetchGet(fullRequest, ctx, url);
    }

    private void fetchGet(final FullHttpRequest inbound, final ChannelHandlerContext ctx, final String url) {
        final StringBuilder buffer = new StringBuilder("");
        final Request request = new Request.Builder()
                .url(url)
                .header("java", inbound.headers().get("java"))
                .get().build();

        final Call call     = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                getSemaphoreInstance().release();//释放
                try {
                    throw e;
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            @SneakyThrows
            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                handleResponse(inbound, ctx, response);
                getSemaphoreInstance().release();//释放
            }
        });
        try {
            getSemaphoreInstance().acquire();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
    }

    private void handleResponse(final FullHttpRequest fullRequest, final ChannelHandlerContext ctx, final Response response) throws Exception {
        FullHttpResponse fullHttpResponse = null;
        try {
            byte[] body = response.body().bytes();

            fullHttpResponse = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(body));

            fullHttpResponse.headers().set("Content-Type", "application/json");
            fullHttpResponse.headers().setInt("Content-Length", Integer.parseInt(response.header("Content-Length")));

            responseFilter.filter(fullHttpResponse);

        } catch (Exception e) {
            e.printStackTrace();
            fullHttpResponse = new DefaultFullHttpResponse(HTTP_1_1, NO_CONTENT);
        } finally {
            if (fullRequest != null) {
                if (!HttpUtil.isKeepAlive(fullRequest)) {
                    ctx.write(fullHttpResponse).addListener(ChannelFutureListener.CLOSE);
                } else {
                    ctx.write(fullHttpResponse);
                }
            }
            ctx.flush();
        }
    }


}
